<?php

declare(strict_types=1);

namespace App\Listener\Models;

use App\Constants\Admin\AdminLogCode;
use App\Model\Model;
use Hyperf\Database\Model\Events\Created;
use Hyperf\Database\Model\Events\Creating;
use Hyperf\Database\Model\Events\Deleted;
use Hyperf\Database\Model\Events\Saving;
use Hyperf\Database\Model\Events\Updated;
use Hyperf\DbConnection\Db;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Event\Contract\ListenerInterface;
use function Hyperf\Coroutine\co;

#[Listener]
class HandleListener implements ListenerInterface
{
    public function __construct()
    {
    }

    public function listen(): array
    {
        return [
            Updated::class,
            Creating::class,
            Created::class,
            Saving::class
        ];
    }

    public function process(object $event): void
    {
        if ($event instanceof Updated) {
            /** @var Model $model */
            $model = $event->getModel();
            if (method_exists($model, 'addLog')) {
                co(function () use ($model) {
                    $model->addLog(AdminLogCode::TYPE_EDIT);
                });
            }
        } elseif ($event instanceof Creating) {
            /** @var Model $model */
            $model = $event->getModel();
            if (isset($model->insert) && $model->insert) {
                foreach ($model->insert as $key => $insert) {
                    if (is_int($key) && !isset($model->$insert)) {
                        $model->$insert = null;
                    } elseif (!is_int($key) && !isset($model->$key)) {
                        $model->$key = $insert;
                    }
                }
            }
        } elseif ($event instanceof Created) {
            /** @var Model $model */
            $model = $event->getModel();
            if (method_exists($model, 'addLog')) {
                co(function () use ($model) {
                    $model->addLog(AdminLogCode::TYPE_CREATE);
                });
            }
        } elseif ($event instanceof Deleted) {
            /** @var Model $model */
            $model = $event->getModel();
            if (method_exists($model, 'addLog')) {
                co(function () use ($model) {
                    $model->addLog(AdminLogCode::TYPE_DELETE);
                });
            }
        } elseif ($event instanceof Saving) {
            /** @var Model $model */
            $model = $event->getModel();
            if (isset($model->geometry) && $model->geometry) {
                foreach ($model->geometry as $column) {
                    if (isset($model->$column) && $model->$column && count(explode(' ', $model->$column)) === 2) {
                        $model->$column = Db::raw("ST_GeometryFromText('POINT({$model->$column})')");
                    }
                }
            }
        }
    }
}
